import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * 基于TCP协议的服务端
 */
public class TCPEchoServer {
    //声明用于服务器通讯的对象
    protected ServerSocket socket;

    //创建端口号及服务器对象
    public TCPEchoServer(int port) throws IOException {
        if(port < 1024 || port > 65535) {
            throw new BindException("端口号异常..");
        }
        this.socket = new ServerSocket(port);
    }
    //处理用户连接请求
    public void start() throws IOException {
        System.out.println("TCP服务器已启动...");
        //循环处理用户连接请求
        while (true) {
            //接收用户连接请求，未连接就阻塞等待
            Socket clientSocket = socket.accept();
            //处理用户发送的数据,放在一个方法中，便于维护
            processConnections(clientSocket);
        }
    }

    protected void processConnections(Socket clientSocket) {
        //打印连接日志
        System.out.printf("%s:%d,客户端上线了\n",
                clientSocket.getInetAddress().toString(),clientSocket.getPort());
        //通过输入输出流处理数据
        try(InputStream inputStream = clientSocket.getInputStream();
            OutputStream outputStream = clientSocket.getOutputStream()
        ) {
            //循环处理数据
            while (true) {
                //使用Scanner简化输入数据
                Scanner scanner = new Scanner(inputStream);
                //判断是否还有数据
                if(!scanner.hasNextLine()) {
                    System.out.printf("%s:%d,客户端下线了\n",
                            clientSocket.getInetAddress().toString(),clientSocket.getPort());
                    break;
                }
                //接收输入数据
                String request = scanner.nextLine();
                //解析输入数据
                String response = process(request);
                //通过Print Writer简化输入
                PrintWriter printWriter = new PrintWriter(outputStream);
                //返回客户端的数据
                printWriter.println(response);
                //printWriter.write(response);不会自带\n 与客户端协议不符
                //刷新缓存区
                printWriter.flush();
                //打印日志
                System.out.printf("request = %s,response = %s",request,response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    protected String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TCPEchoServer tcpEchoServer = new TCPEchoServer(9999);
        tcpEchoServer.start();
    }
}
